package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.BizStatusEnum;
import cc.rengu.igas.momp.common.enums.MchntTypeEnum;
import cc.rengu.igas.momp.common.enums.RespCodeEnum;
import cc.rengu.igas.momp.facade.request.ComboMchntFeeDiscountReversalRequest;
import cc.rengu.igas.momp.facade.response.ComboMchntFeeDiscountReversalResponse;
import cc.rengu.jradp.mods.dbs.Database;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DbsUtil;
import cc.rengu.oltp.utility.util.XmlConfigUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.StringUtil;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author liujinan
 * @version 1.0.0
 * @date 2020/5/7
 * @description 手续费优惠支付冲正接口实现
 */
public class ComboMchntFeeDiscountReversalService extends RadpService {
    private String globalTimeStamp;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            ComboMchntFeeDiscountReversalRequest comboMchntFeeDiscountReversalRequest = new ComboMchntFeeDiscountReversalRequest();
            ConvertUtil.convertOutput(comboMchntFeeDiscountReversalRequest);

            ComboMchntFeeDiscountReversalResponse comboMchntFeeDiscountReversalResponse = new ComboMchntFeeDiscountReversalResponse();
            comboMchntFeeDiscountReversalResponse.setHeader(comboMchntFeeDiscountReversalRequest.getHeader());
            BizResponse<ComboMchntFeeDiscountReversalResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(comboMchntFeeDiscountReversalResponse);

            //接口请求报文检查
            checkRequestMessage(comboMchntFeeDiscountReversalRequest);

            globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

            // 调用处理流程
            BizResponse<ComboMchntFeeDiscountReversalResponse> bizResponseNew = comboMchntFeeDiscountReversal(xmlTreeUtil, comboMchntFeeDiscountReversalRequest, comboMchntFeeDiscountReversalResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());
        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e));
            }
        }
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 手续费优惠支付冲正
     *
     * @param comboMchntFeeDiscountReversalRequest
     * @param comboMchntFeeDiscountReversalResponse
     * @param xmlTreeUtil                           内部XML树
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/11
     */
    private BizResponse<ComboMchntFeeDiscountReversalResponse> comboMchntFeeDiscountReversal(XmlTreeUtil xmlTreeUtil, ComboMchntFeeDiscountReversalRequest comboMchntFeeDiscountReversalRequest, ComboMchntFeeDiscountReversalResponse comboMchntFeeDiscountReversalResponse) throws Exception {
        BizResponse<ComboMchntFeeDiscountReversalResponse> bizResponse = new BizResponse<>();
        rglog.debug("交易类型 TXN_NUM = {}", comboMchntFeeDiscountReversalRequest.getHeader().getTxnNum());

        String instId = comboMchntFeeDiscountReversalRequest.getHeader().getInstId();
        String transDate = comboMchntFeeDiscountReversalRequest.getHeader().getTransDate();
        String origTraceNo = comboMchntFeeDiscountReversalRequest.getOrigTraceNo();

        // 开启数据库事务
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        try {
            //查询原交易订单流水信息
            TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
            TMTxnOrder tmTxnOrder = tmTxnOrderMapper.selectFeeDiscountOriginalTransactionOrderInfo(instId, transDate, origTraceNo);

            if (null != tmTxnOrder) {
                //冲正逻辑处理
                int returnCode = checkAndProcessReversalProcedure(tmTxnOrder);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("机构<{}>在<{}>的原交易<{}>冲正失败!", instId, transDate, origTraceNo);

                    bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
                    bizResponse.setRespCode(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode());
                    bizResponse.setRespDesc(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());

                    comboMchntFeeDiscountReversalResponse.setRespCode(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode());
                    comboMchntFeeDiscountReversalResponse.setRespDesc(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());

                    bizResponse.setResult(comboMchntFeeDiscountReversalResponse);

                    //事务处理失败关闭数据库事务
                    dbsUtil.dbsEndTransaction(false);

                    return bizResponse;
                }
            } else {
                rglog.info("查询机构<{}>在<{}>的原交易订单流水信息<{}>失败，直接返回冲正成功", instId, transDate, origTraceNo);
            }
        } catch (Exception e) {
            rglog.error("机构<{}> 交易日期<{}> 交易流水<{}> 冲正处理失败!", instId, transDate, origTraceNo);
            //事务处理失败关闭数据库事务
            dbsUtil.dbsEndTransaction(false);
            throw new Exception(e);
        }
        //事务处理成功关闭数据库事务
        dbsUtil.dbsEndTransaction(true);

        rglog.info("机构<{}>在<{}>的原交易<{}>冲正成功!", instId, transDate, origTraceNo);

        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        comboMchntFeeDiscountReversalResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        comboMchntFeeDiscountReversalResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(comboMchntFeeDiscountReversalResponse);
        return bizResponse;
    }

    /**
     * 判断和处理手续费优惠冲正处理流程
     *
     * @param tmTxnOrder
     * @return int
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/7 10:16
     */
    private int checkAndProcessReversalProcedure(TMTxnOrder tmTxnOrder) throws Exception {
        String tmTxnOrderBizStatus = tmTxnOrder.getBizStatus();

        if (BizStatusEnum.PROCESS_FAILED.getBizStatusCode().equals(tmTxnOrderBizStatus) ||
                BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode().equals(tmTxnOrderBizStatus) ||
                BizStatusEnum.PROCESS_REFUND_REVERSED.getBizStatusCode().equals(tmTxnOrderBizStatus)) {
            //原交易已冲正,或失败,不可继续冲正
            rglog.info("机构<{}>在<{}>的原交易<{}> 状态为<{}>,无需继续冲正处理(02:业务处理失败 20：已消费冲正 AA:已退货冲正)，返回冲正成功!", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), tmTxnOrderBizStatus);
            return CommonConstant.PROCESS_SUCCESS;
        }

        String orderRemark = tmTxnOrder.getOrderRemark();
        //判断如果是没有优惠的，并且原交易是成功的，需要更新原交易为已冲正（这里不用判断无优惠原交易是失败的情况，如果失败在上步就已经返回）
        if (BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(tmTxnOrderBizStatus) && CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE.equals(orderRemark)) {
            /* 更新订单流水表业务状态 */
            int returnCode = updateTxnOrderBizStatusInfo(tmTxnOrder, BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode());
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("更新原交易订单流水表流水<{}>状态失败!", tmTxnOrder.getFrontSeqNum());
                throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
            }
            rglog.info("机构<{}>在<{}>的原交易<{}> 为成功的交易，但订单无任何优惠信息! orderRemark：<{}>,更新原交易为已冲正，返回冲正成功！", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), orderRemark);
            return CommonConstant.PROCESS_SUCCESS;
        }

        //手续费优惠冲正流程
        rglog.info("机构<{}>在<{}>的原交易<{}>状态为<{}>,可进行冲正处理", tmTxnOrder.getInstId(), tmTxnOrder.getTxnDate(), tmTxnOrder.getFrontSeqNum(), tmTxnOrderBizStatus);
        feeDiscountReversalOperation(tmTxnOrder);

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 手续费优惠冲正处理流程
     *
     * @param tmTxnOrder
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/7 10:13
     */
    private void feeDiscountReversalOperation(TMTxnOrder tmTxnOrder) throws Exception {

        String instId = tmTxnOrder.getInstId();
        String transDate = tmTxnOrder.getTxnDate();
        String origTraceNo = tmTxnOrder.getFrontSeqNum();
        // 查询原始交易订单明细
        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        List<TMTxnOrderDet> tmTxnOrderDetList = tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, transDate, origTraceNo);

        if (null == tmTxnOrderDetList || tmTxnOrderDetList.isEmpty()) {
            rglog.error("获取机构<{}>在<{}>的流水号<{}>的订单明细信息失败!", instId, transDate, origTraceNo);
            throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
        }

        // 商户手续费优惠冲正处理流程
        feeDiscountReversalProcedure(tmTxnOrder, tmTxnOrderDetList);
        //更新订单流水表业务状态
        int returnCode = updateTxnOrderBizStatusInfo(tmTxnOrder, BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode());
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新订单流水<{}>表数据失败!所有数据库操作回滚!", tmTxnOrder.getFrontSeqNum());
            throw new BizException(RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespCode(), RespCodeEnum.REVERSAL_PROCEDURE_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 手续费优惠冲正
     *
     * @param tmTxnOrderDetList
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/7 10:34
     */
    private void feeDiscountReversalProcedure(TMTxnOrder tmTxnOrder, List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {
        //手续费减免活动单日统计表
        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        //手续费减免活动商户单日统计表
        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        //订单明细表
        TMTxnOrderDetMapper TmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        //手续费减免达标数据统计表
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();

        //循环遍历订单明细表处理商户手续费营销活动统计数据
        for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetList) {

            //原交易登记的活动规则编号
            String ruleIndex = tmTxnOrderDet.getRuleIndex();
            //判断如果活动规则编号为0时，这笔原交易应该是活动期间新入驻商户免手续费的情况，这个时候不需要更新统计数据（新入驻商户免手续费支付时也并未登记或更新统计表）
            rglog.info("机构<{}> 交易日期<{}> 流水<{}> 规则编号<{}> ", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), ruleIndex);

            //更新手续费减免活动单日统计表数据 T_M_STAT_MFD_DAY
            TMStatMfdDay tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setInstId(tmTxnOrderDet.getInstId());
            tmStatMfdDay.setMcNo(tmTxnOrderDet.getMcNo());
            tmStatMfdDay.setTxnDate(tmTxnOrderDet.getTxnDate());
            tmStatMfdDay.setRuleIndex(tmTxnOrderDet.getRuleIndex());

            //原统计表中的值减去冲正这笔交易的值
            String totalAmtAcc = new BigDecimal(tmTxnOrderDet.getSubsidy()).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();

            //关联信息
            String relativeData = tmTxnOrderDet.getRelativeData();
            JSONObject relativeDataJson = JSONObject.parseObject(relativeData);
            String disTxAmt = tmTxnOrderDet.getDisTxAmt();
            String txnAmtAcc;
            if (null != disTxAmt) {
                txnAmtAcc = new BigDecimal(disTxAmt).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
            } else {
                //获取明细中的订单金额（商户清算金额）
                String orderAmtString = relativeDataJson.get("orderAmt").toString();
                txnAmtAcc = new BigDecimal(orderAmtString).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
            }

            //累计优惠笔数  更新数据库时的加值  负1
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            //累计优惠金额
            tmStatMfdDay.setTotalAmtAcc(totalAmtAcc);
            //累计交易笔数
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            //累计交易金额
            tmStatMfdDay.setTxnAmtAcc(txnAmtAcc);

            tmStatMfdDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay.setUpdateTime(globalTimeStamp);

            tmStatMfdDay.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay.setPaidAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay.setCreateTime(globalTimeStamp);

            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动单日统计表...", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
            int returnCode = tmStatMfdDayMapper.reverseMchntFeeDiscountDayStatistics(tmStatMfdDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }

            //如果当规则不是0 ，则还需要更新规则为0的记录
            if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay.getRuleIndex())) {
                tmStatMfdDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                returnCode = tmStatMfdDayMapper.reverseMchntFeeDiscountDayStatistics(tmStatMfdDay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                        int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                            /* 插入数据失败 */
                            rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                        }
                    } else {
                        /* 更新数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                }
            }

            String mchntNo = tmTxnOrderDet.getMchntNo();
            MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
            TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(tmTxnOrderDet.getInstId(), mchntNo);
            if (null == mchntBaseInfo) {
                //查询不到商户信息，流程结束
                rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", tmTxnOrderDet.getInstId(), mchntNo);
                throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
            }
            //商户性质
            String mchntType = mchntBaseInfo.getMchntType();
            //独立营销活动标识
            String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
            //连锁商户号
            String chainMchntNo = mchntBaseInfo.getChainMchntNo();
            //是否独立维护商户资料
            String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
            if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
                rglog.info("商户<{}> 商户类型为11:连锁商户门店，商户独立营销活动标识为<{}> 是否独立维护商户资料<{}> 原正向交易计算营销时根据上级商户<{}> 获取营销活动计算的!", mchntNo, idpdCmavyFlg, independentDataFlag, chainMchntNo);
                mchntNo = chainMchntNo;
            } else {
                rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 原正向交易无需判断独立营销活动标识，均使用当前商户号计算的营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, idpdCmavyFlg);
            }

            // 更新手续费减免活动商户单日统计表 T_M_STAT_MFD_MCHNT_DAY
            TMStatMfdMchntDay tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setInstId(tmTxnOrderDet.getInstId());
            tmStatMfdMchntDay.setMcNo(tmTxnOrderDet.getMcNo());
            tmStatMfdMchntDay.setTxnDate(tmTxnOrderDet.getTxnDate());
            tmStatMfdMchntDay.setMchntNo(mchntNo);
            tmStatMfdMchntDay.setRuleIndex(tmTxnOrderDet.getRuleIndex());

            //原统计表中的值减去冲正这笔交易的值
            String mcTotalAmtAcc = new BigDecimal(tmTxnOrderDet.getSubsidy()).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();

            //累计优惠笔数
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            //累计优惠金额
            tmStatMfdMchntDay.setTotalAmtAcc(mcTotalAmtAcc);
            //累计交易笔数
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            //累计交易金额
            tmStatMfdMchntDay.setTxnAmtAcc(txnAmtAcc);

            tmStatMfdMchntDay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay.setUpdateTime(globalTimeStamp);

            tmStatMfdMchntDay.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay.setCreateTime(globalTimeStamp);

            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表...", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex());
            returnCode = tmStatMfdMchntDayMapper.reverseMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                    int returnCode2 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }

            //如果当规则不是0 ，则还需要更新规则为0的记录
            if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay.getRuleIndex())) {
                tmStatMfdMchntDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                rglog.info("机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表...", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex());
                returnCode = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                        int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                            /* 插入数据失败 */
                            rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                        }
                    } else {
                        /* 更新数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                }
            }

            //业务状态_已冲正
            tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_PAYMENT_REVERSED.getBizStatusCode());
            tmTxnOrderDet.setUpdateTime(globalTimeStamp);
            //更新原手续费优惠订单明细
            int updateTmTxnOrderDetCode = TmTxnOrderDetMapper.updateTmTxnOrderDetByKey(tmTxnOrderDet);
            if (Database.DBS_SUCCESS != updateTmTxnOrderDetCode) {
                rglog.error("更新手续费优惠订单明细表数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                        tmTxnOrderDet.getInstId(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId(), tmTxnOrderDet.getMchntNo());
                throw new BizException(RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespCode(), RespCodeEnum.FAILED_UPDATE_T_M_TXN_ORDER_DET.getRespDesc());
            }

            TMStatMfdCriteria tmStatMfdCriteria = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndMcNoAndDateRange(tmTxnOrderDet.getInstId(), mchntNo, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getMcNo());
            rglog.info("交易流水号<{}>,机构<{}>的商户<{}>查询商户手续费减免达标数据统计表", tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getInstId(), mchntNo);
            if (null != tmStatMfdCriteria) {
                //判断商户优惠退出状态exit_discount_status，如果已经退出，冲正后需要还原为未退出？
                String exit_discount_status = tmStatMfdCriteria.getExitDiscountStatus();
                //判断退出标识是否已退出,如果是,则置为未退出
                if (CommonConstant.MC_EXIT_FLAG.equals(exit_discount_status)) {
                    tmStatMfdCriteria.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
                    tmStatMfdCriteria.setUpdateTime(globalTimeStamp);
                    tmStatMfdCriteria.setExitDiscountStatus(CommonConstant.MC_NOT_EXIT_FLAG);
                    rglog.info("交易流水号<{}>,机构<{}>的商户<{}>更新商户手续费减免达标数据统计表", tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getInstId(), mchntNo);
                    int updateReturnCode = tmStatMfdCriteriaMapper.updateTMstatMfdCriteriaByPrimaryKey(tmStatMfdCriteria);
                    if (updateReturnCode != 0) {
                        rglog.error("机构<{}> 商户<{}> 营销活动编号<{}> 根据主键更新营销活动手续费减免达标数据统计表失败！",
                                tmStatMfdCriteria.getInstId(), mchntNo, tmStatMfdCriteria.getMcNo());
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    rglog.info("交易流水号<{}>,机构<{}>的商户<{}> 商户手续费减免达标数据统计表退出状态为 未退出，无需更新退出状态，流程继续", tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getInstId(), mchntNo);
                }
            } else {
                rglog.info("交易流水号<{}>,机构<{}>的商户<{}>查询商户手续费减免达标数据统计表失败！", tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getInstId(), mchntNo);
                throw new BizException(RespCodeEnum.GET_STATISTICAL_DATA_ERROR.getRespCode(), RespCodeEnum.GET_STATISTICAL_DATA_ERROR.getRespDesc());
            }
        }
    }

    /**
     * 更新订单流水表业务状态
     *
     * @param tmTxnOrder
     * @param bizStatus
     * @return int
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/7 11:40
     */
    private int updateTxnOrderBizStatusInfo(TMTxnOrder tmTxnOrder, String bizStatus) throws Exception {

        tmTxnOrder.setUpdateTime(globalTimeStamp);
        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCode = tmTxnOrderMapper.updateFeeDiscountOriginalTransactionOrderBizStatus(tmTxnOrder, bizStatus);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("机构<{}> 交易流水<{}> 更新订单流水表业务状态失败!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum());
            return CommonConstant.PROCESS_FAILED;
        } else {
            return CommonConstant.PROCESS_SUCCESS;
        }
    }

    /**
     * 请求报文检查
     *
     * @param comboMchntFeeDiscountReversalRequest
     * @throws BizException 异常信息
     * @author liujinan
     * @date 2020/6/11
     */
    private void checkRequestMessage(ComboMchntFeeDiscountReversalRequest comboMchntFeeDiscountReversalRequest) throws BizException {

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountReversalRequest.getOrigTraceNo())) {
            rglog.error("原交流水号为空,需要上送原交流水号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
    }

    /**
     * 使用商户编号和当前交易日期获取商户当前统计周期内已参加的商户手续费优惠营销活动统计数据
     *
     * @param instId
     * @param mchntNo
     * @param transDate
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdCriteria
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/5
     */
    private TMStatMfdCriteria selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(String instId, String mchntNo, String transDate) throws Exception {
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        return tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(instId, mchntNo, transDate);
    }
}
